home *** CD-ROM | disk | FTP | other *** search
Oberon Text | 1995-04-11 | 16.6 KB | 545 lines | [TEXT/.Ob4] |
- Syntax10.Scn.Fnt
- MODULE KeplerGraphs; (* J. Templ, 30.10.90 *)
- IMPORT SYSTEM, KeplerPorts, Display, Files, Oberon, Modules, Types, Texts;
- CONST
- draw* = 0; restore* = 1; (* notify op-codes *)
- ptSize = 12;
- maxNofpts = 4;
- (* graph = {star} {configuration} 0X.
- star = header contents.
- configuration = header contents.
- header = typeref [typename].
- typeref = compact-integer.
- typename = qualident 0X.
- contents = {byte}. *)
- TYPE
- Object* = POINTER TO ObjectDesc;
- ObjectDesc* = RECORD END ;
- Star* = POINTER TO StarDesc;
- StarDesc* = RECORD
- (ObjectDesc)
- x*, y*, refcnt*, ref: INTEGER;
- sel*: BOOLEAN;
- next* : Star;
- END ;
- Constellation* = POINTER TO ConsDesc;
- ConsDesc* = RECORD
- (ObjectDesc)
- nofpts*: INTEGER;
- p*: ARRAY maxNofpts OF Star;
- next*: Constellation;
- END ;
- Planet* = POINTER TO PlanetDesc;
- PlanetDesc* = RECORD
- (StarDesc)
- c*: Constellation;
- END;
- Graph* = POINTER TO GraphDesc;
- Notifier* = PROCEDURE (op: INTEGER; G: Graph; O: Object; P: KeplerPorts.Port);
- GraphDesc* = RECORD
- (ObjectDesc)
- cons*, lastcons: Constellation;
- stars*, laststar: Star;
- seltime*: LONGINT;
- notify*: Notifier;
- END ;
- StarTab = POINTER TO ARRAY OF LONGINT;
- loading*: Graph;
- update: KeplerPorts.BalloonPort;
- nofpt: INTEGER;
- starTab: StarTab;
- noftypes: LONGINT;
- typTab: ARRAY 256 OF LONGINT;
- del, delG: Graph;
- (* ---------------------------------- abstract methods ---------------------------------- *)
- PROCEDURE (self: Object) Draw* (P: KeplerPorts.Port);
- END Draw;
- PROCEDURE (self: Object) Read* (VAR R: Files.Rider);
- END Read;
- PROCEDURE (self: Object) Write* (VAR R: Files.Rider);
- END Write;
- (* ---------------------------------- auxiliary procedures ---------------------------------- *)
- PROCEDURE err(s0, s1: ARRAY OF CHAR);
- VAR W: Texts.Writer;
- BEGIN Texts.OpenWriter(W);
- Texts.WriteString(W, s0); Texts.WriteString(W, s1); Texts.WriteLn(W);
- Texts.Append(Oberon.Log, W.buf)
- END err;
- PROCEDURE err2(s0, s1: ARRAY OF CHAR);
- VAR W: Texts.Writer;
- BEGIN Texts.OpenWriter(W);
- Texts.WriteString(W, s0); Texts.WriteString(W, s1);
- Texts.Append(Oberon.Log, W.buf)
- END err2;
- PROCEDURE ReadObj* (VAR R: Files.Rider; VAR x: Object);
- VAR ref: LONGINT;
- m: Modules.Module; t: Types.Type;
- module, type: ARRAY 32 OF CHAR;
- BEGIN x := NIL;
- Files.ReadNum(R, ref);
- IF ref = noftypes THEN
- Files.ReadString(R, module);
- Files.ReadString(R, type);
- m := Modules.ThisMod(module);
- IF m # NIL THEN t := Types.This(m, type);
- IF t # NIL THEN typTab[ref] := SYSTEM.VAL(LONGINT, t); INC(noftypes);
- Types.NewObj(x, t); x.Read(R)
- ELSE err("-- type not found: ", type)
- END
- ELSE err2("-- error: ", Modules.importing);
- IF Modules.res = 2 THEN err(" not an obj-file", "")
- ELSIF Modules.res = 3 THEN err2(" imports ", Modules.imported); err(" with bad key", "");
- ELSIF Modules.res = 4 THEN err(" corrupted obj file", "")
- ELSIF Modules.res = 7 THEN err(" not enough space", "")
- END;
- (*Modules.res := 0*)
- END
- ELSIF ref # -1 THEN
- Types.NewObj(x, SYSTEM.VAL(Types.Type, typTab[ref]));
- x.Read(R)
- END
- END ReadObj;
- PROCEDURE WriteObj* (VAR R: Files.Rider; x: Object);
- VAR typ: Types.Type; i: LONGINT;
- BEGIN
- IF x # NIL THEN
- typ := Types.TypeOf(x); i := 0;
- WHILE (i < noftypes) & (SYSTEM.VAL(LONGINT, typ) # typTab[i]) DO INC(i) END ;
- IF i = noftypes THEN
- Files.WriteNum(R, i);
- typTab[i] := SYSTEM.VAL(LONGINT, typ); INC(noftypes);
- Files.WriteString(R, typ.module.name);
- Files.WriteString(R, typ.name)
- ELSE
- Files.WriteNum(R, i)
- END ;
- x.Write(R)
- ELSE Files.WriteNum(R, -1)
- END
- END WriteObj;
- PROCEDURE GetType* (o: Object; VAR module, type: ARRAY OF CHAR);
- VAR t: Types.Type;
- BEGIN t := Types.TypeOf(o); COPY(t.module.name, module); COPY(t.name, type)
- END GetType;
- PROCEDURE Reset*;
- BEGIN nofpt := 0; noftypes := 0
- END Reset;
- PROCEDURE GetStar (n: INTEGER): Star;
- VAR s: Star;
- BEGIN s := SYSTEM.VAL(Star, starTab[n]); INC(s.refcnt); RETURN s
- END GetStar;
- (* ---------------------------------- Star methods ---------------------------------- *)
- PROCEDURE (self: Star) Draw* (P: KeplerPorts.Port);
- BEGIN
- IF self.sel THEN
- P.FillRect(self.x - ptSize, self.y - ptSize, ptSize*2 + P.scale, ptSize*2 + P.scale, Display.white, 5, Display.invert)
- END
- END Draw;
- PROCEDURE (self: Star) Read* (VAR R: Files.Rider);
- VAR h: LONGINT;
- BEGIN self.sel := FALSE;
- Files.ReadNum(R, h); self.x := SHORT(h);
- Files.ReadNum(R, h); self.y := SHORT(h)
- END Read;
- PROCEDURE (self: Star) Write* (VAR R: Files.Rider);
- BEGIN
- Files.WriteNum(R, self.x);
- Files.WriteNum(R, self.y)
- END Write;
- (* ---------------------------------- Constellation methods ---------------------------------- *)
- PROCEDURE (self: Constellation) State* (): INTEGER; (* unselected = 0; partially selected = 1; totally selected = 2 *)
- VAR sum, i: INTEGER;
- BEGIN sum := 0; i := 0;
- WHILE i < self.nofpts DO
- IF self.p[i].sel THEN INC(sum) END ;
- INC(i)
- END ;
- IF sum = 0 THEN RETURN 0
- ELSIF sum = self.nofpts THEN RETURN 2
- ELSE RETURN 1
- END
- END State;
- PROCEDURE (self: Constellation) Read* (VAR R: Files.Rider);
- VAR ref, i: LONGINT;
- BEGIN i := 0;
- Files.ReadNum(R, ref); self.nofpts := SHORT(ref);
- i := 0;
- WHILE i < self.nofpts DO
- Files.ReadNum(R, ref);
- self.p[i] := GetStar(SHORT(ref));
- INC(i)
- END
- END Read;
- PROCEDURE (self: Constellation) Write* ( VAR R: Files.Rider);
- VAR i: INTEGER;
- BEGIN i := 0;
- Files.WriteNum(R, self.nofpts);
- WHILE i < self.nofpts DO Files.WriteNum(R, self.p[i].ref); INC(i) END
- END Write;
- (* ---------------------------------- Planet methods ---------------------------------- *)
- PROCEDURE (self: Planet) Draw* (P: KeplerPorts.Port);
- BEGIN
- IF self.sel THEN
- P.DrawRect(self.x - ptSize, self.y - ptSize, ptSize*2, ptSize*2, Display.white, Display.invert)
- END
- END Draw;
- PROCEDURE (self: Planet) Calc*;
- END Calc;
- PROCEDURE (self: Planet) Read* (VAR R: Files.Rider);
- VAR o: Object;
- BEGIN self.Read^(R); ReadObj(R, o); self.c := o(Constellation)
- END Read;
- PROCEDURE (self: Planet) Write* (VAR R: Files.Rider);
- BEGIN self.Write^(R); WriteObj(R, self.c)
- END Write;
- (* ---------------------------------- Graphic methods ---------------------------------- *)
- PROCEDURE (G: Graph) Append*(o: Object);
- BEGIN
- IF o IS Star THEN
- WITH o: Star DO
- IF G.stars = NIL THEN G.stars := o ELSE G.laststar.next := o END ;
- G.laststar := o; o.next := NIL
- END
- ELSE
- WITH o: Constellation DO
- IF G.cons = NIL THEN G.cons := o ELSE G.lastcons.next := o END ;
- G.lastcons := o; o.next := NIL;
- G.notify(draw, G, o, NIL)
- END
- END
- END Append;
- PROCEDURE (G: Graph) FlipSelection*(p: Star);
- BEGIN
- IF p.sel THEN G.notify(draw, G, p, NIL); p.sel := FALSE
- ELSE p.sel := TRUE; G.notify(draw, G, p, NIL); G.seltime := Oberon.Time()
- END
- END FlipSelection;
- PROCEDURE DependsOn(c: Constellation; s: Star): BOOLEAN;
- VAR i: INTEGER; p: Star;
- BEGIN i := 0;
- WHILE i < c.nofpts DO p := c.p[i];
- IF p = s THEN RETURN TRUE
- ELSIF (p IS Planet) & DependsOn(p(Planet).c, s) THEN RETURN TRUE
- END ;
- INC(i)
- END ;
- RETURN FALSE
- END DependsOn;
- PROCEDURE (G: Graph) Move*(s: Star; dx, dy: INTEGER);
- VAR p: Star; c: Constellation;
- BEGIN
- KeplerPorts.InitBalloon(update);
- c := G.cons;
- WHILE c # NIL DO
- IF DependsOn(c, s) THEN c.Draw(update) END ;
- c := c.next
- END ;
- p := s^.next;
- WHILE p # NIL DO
- IF (p IS Planet) & DependsOn(p(Planet).c, s) THEN p.Draw(update) END ;
- p := p.next
- END ;
- s.Draw(update); INC(s.x, dx); INC(s.y, dy); s.Draw(update);
- p := s^.next;
- WHILE p # NIL DO
- IF (p IS Planet) & DependsOn(p(Planet).c, s) THEN p(Planet).Calc; p.Draw(update) END ;
- p := p.next
- END ;
- c := G.cons;
- WHILE c # NIL DO
- IF DependsOn(c, s) THEN c.Draw(update) END ;
- c := c.next
- END ;
- G.notify(restore, G, NIL, update)
- END Move;
- PROCEDURE (G: Graph) MoveSelection*(dx, dy: INTEGER);
- VAR p: Star; c: Constellation;
- BEGIN
- KeplerPorts.InitBalloon(update);
- p := G.stars;
- WHILE p # NIL DO (*expand selection*)
- IF ~p.sel & (p IS Planet) & (p(Planet).c.State() > 0) THEN p.sel := TRUE END ;
- p := p.next
- END ;
- c := G.cons;
- WHILE c # NIL DO
- IF c.State() # 0 THEN c.Draw(update) END ;
- c := c.next
- END ;
- p := G.stars;
- WHILE p # NIL DO
- IF p.sel THEN
- p.Draw(update);
- IF p IS Planet THEN p(Planet).Calc
- ELSE INC(p.x, dx); INC(p.y, dy)
- END ;
- p.Draw(update)
- END ;
- p := p.next
- END ;
- c := G.cons;
- WHILE c # NIL DO
- IF c.State() # 0 THEN c.Draw(update) END ;
- c := c.next
- END ;
- G.notify(restore, G, NIL, update)
- END MoveSelection;
- PROCEDURE ReverseStars(G: Graph);
- VAR p, first, next: Star;
- BEGIN p := G.stars;
- G.laststar := p; first := NIL;
- WHILE p # NIL DO
- next := p.next; p.next := first;
- first := p; p := next
- END ;
- G.stars := first
- END ReverseStars;
- PROCEDURE Release (self: Constellation);
- VAR i: INTEGER; s: Star;
- BEGIN i := 0;
- WHILE i < self.nofpts DO s := self.p[i]; DEC(s.refcnt); INC(i) END
- END Release;
- PROCEDURE CutCons (G: Graph; prevc, c: Constellation);
- BEGIN
- IF prevc = NIL THEN G.cons := c.next ELSE prevc.next := c.next END ;
- IF del.cons = NIL THEN del.cons := c ELSE del.lastcons.next := c END ;
- del.lastcons := c;
- IF G.lastcons = c THEN G.lastcons:= prevc END ;
- Release(c); c.Draw(update)
- END CutCons;
- PROCEDURE CutStar (G:Graph; prevs, s: Star);
- BEGIN
- IF prevs = NIL THEN G.stars := s.next ELSE prevs.next := s.next END ;
- IF del.stars = NIL THEN del.stars := s ELSE del.laststar.next := s END ;
- del.laststar := s;
- IF G.laststar = s THEN G.laststar := prevs END ;
- IF s IS Planet THEN Release(s(Planet).c) END ;
- s.ref := 0;
- s.Draw(update)
- END CutStar;
- PROCEDURE DelStar(G: Graph; o: Object);
- VAR s, prevs: Star;
- BEGIN
- s := G.stars; prevs := NIL;
- WHILE (s # NIL) & (s # o) DO prevs := s; s := s.next END ;
- IF s # NIL THEN CutStar(G, prevs, s) END
- END DelStar;
- PROCEDURE (G: Graph) Delete* (o: Object);
- VAR c, prevc: Constellation; i: INTEGER;
- BEGIN
- KeplerPorts.InitBalloon(update);
- delG := G; del.cons := NIL; del.stars := NIL;
- IF o IS Constellation THEN
- c := G.cons; prevc := NIL;
- WHILE (c # NIL) & (c # o) DO prevc := c; c := c.next END ;
- IF c # NIL THEN
- CutCons(G, prevc, c); i := 0;
- WHILE i < c.nofpts DO
- IF (c.p[i].refcnt = 0) & ~(c.p[i] IS Planet) THEN DelStar(G, c.p[i]) END ;
- INC(i)
- END
- END
- ELSE ASSERT(o(Star).refcnt = 0);
- IF o IS Planet THEN
- c := o(Planet).c; Release(c); i := 0;
- WHILE i < c.nofpts DO
- IF (c.p[i].refcnt = 0) & ~(c.p[i] IS Planet) THEN DelStar(G, c.p[i]) END ;
- INC(i)
- END
- END ;
- DelStar(G, o)
- END ;
- IF del.cons # NIL THEN del.lastcons.next := NIL END ;
- IF del.stars # NIL THEN del.laststar.next := NIL END ;
- G.notify(restore, G, NIL, update)
- END Delete;
- PROCEDURE (G: Graph) DeleteSelection* (minstate: INTEGER);
- VAR s, prevs: Star; c, prevc: Constellation;
- BEGIN
- delG := G; KeplerPorts.InitBalloon(update);
- (*move all constellations with (State >= minstate) into del buffer*)
- c := G.cons; prevc := NIL; del.cons := NIL;
- WHILE c # NIL DO
- IF c.State() >= minstate THEN CutCons(G, prevc, c) ELSE prevc := c END ;
- c := c.next
- END ;
- IF del.cons # NIL THEN del.lastcons.next := NIL END ;
- (*move all unused stars and planets with refcnt=0 & c.State>=minstate into del buffer*)
- ReverseStars(G);
- s := G.stars; prevs := NIL; del.stars := NIL;
- WHILE s # NIL DO
- IF (s.refcnt = 0) & (~(s IS Planet) OR s.sel OR (s(Planet).c.State() >= minstate)) THEN CutStar(G, prevs, s)
- ELSE prevs := s
- END ;
- s := s.next
- END ;
- ReverseStars(G) ;
- IF del.stars # NIL THEN del.laststar.next := NIL; ReverseStars(del) END ;
- G.notify(restore, G, NIL, update)
- END DeleteSelection;
- PROCEDURE (G: Graph) All* (op: INTEGER); (* deselect = 0; select = 1 *)
- VAR p: Star;
- BEGIN p := G.stars;
- KeplerPorts.InitBalloon(update);
- WHILE p # NIL DO
- IF (op = 1) # p.sel THEN
- IF p.sel THEN p.Draw(update); p.sel := FALSE
- ELSE p.sel := TRUE; p.Draw(update); G.seltime := Oberon.Time()
- END
- END ;
- p := p.next
- END ;
- IF op = 0 THEN G.seltime := -1 END ;
- G.notify(restore, G, NIL, update)
- END All;
- PROCEDURE Store(G: Graph; VAR R: Files.Rider; all: BOOLEAN);
- VAR p, dummy: Star; c: Constellation;
- BEGIN
- p := G.stars;
- NEW(dummy);
- WHILE p # NIL DO
- IF all OR (p.sel & ~(p IS Planet)) THEN
- WriteObj(R, p); p.ref := nofpt; INC(nofpt)
- ELSIF p.sel & (p(Planet).c.State() = 2) THEN
- WriteObj(R, p); p.ref := nofpt; INC(nofpt)
- ELSIF p.sel & (p(Planet).c.State() # 2) THEN
- dummy^ := p^; WriteObj(R, dummy); p.ref := nofpt; INC(nofpt)
- END ;
- p := p.next
- END ;
- c := G.cons;
- WHILE c # NIL DO
- IF all OR (c.State()=2) THEN WriteObj(R, c) END ;
- c := c.next
- END ;
- Files.WriteNum(R, -1)
- END Store;
- PROCEDURE (G: Graph) Draw* (P: KeplerPorts.Port);
- VAR s: Star; c: Constellation;
- BEGIN
- c := G.cons;
- WHILE c # NIL DO c.Draw(P); c := c.next END ;
- s := G.stars;
- WHILE s # NIL DO s.Draw(P); s := s.next END
- END Draw;
- PROCEDURE (G: Graph) Write* (VAR R: Files.Rider);
- BEGIN
- Store(G, R, TRUE)
- END Write;
- PROCEDURE (G: Graph) WriteSel* (VAR R: Files.Rider);
- BEGIN Store(G, R, FALSE)
- END WriteSel;
- PROCEDURE DoubleStarTab;
- VAR h: StarTab; i: LONGINT;
- BEGIN i := 0; NEW(h, LEN(starTab^)*2);
- WHILE i < LEN(starTab^) DO h[i] := starTab[i]; INC(i) END ;
- starTab := h
- END DoubleStarTab;
- PROCEDURE (G: Graph) Read* (VAR R: Files.Rider);
- VAR o, o0: Object;
- BEGIN loading := G;
- G.stars := NIL; G.laststar := NIL; G.cons := NIL; G.lastcons := NIL; G.seltime := -1;
- ReadObj(R, o0); o := o0;
- WHILE o # NIL DO (* append without notification *)
- WITH o: Star DO
- IF G.stars = NIL THEN G.stars := o ELSE G.laststar.next := o END ;
- G.laststar := o; o.next := NIL;
- IF nofpt = LEN(starTab^) THEN DoubleStarTab END ;
- starTab[nofpt] := SYSTEM.VAL(LONGINT, o); INC(nofpt)
- | o: Constellation DO
- IF G.cons = NIL THEN G.cons := o ELSE G.lastcons.next := o END ;
- G.lastcons := o; o.next := NIL
- END ;
- ReadObj(R, o)
- END
- END Read;
- PROCEDURE Old*(name: ARRAY OF CHAR): Graph;
- VAR F: Files.File; R: Files.Rider; o: Object;
- BEGIN F := Files.Old(name);
- IF F # NIL THEN Files.Set(R, F, 0); Reset; ReadObj(R, o);
- IF R.res = 0 THEN RETURN o(Graph) ELSE RETURN NIL END
- ELSE RETURN NIL
- END
- END Old;
- PROCEDURE *Dummy(op: INTEGER; g: Graph; c: Object; f: KeplerPorts.Port);
- END Dummy;
- PROCEDURE (G: Graph) CopySelection* (from: Graph; dx, dy: INTEGER);
- VAR cpBuf: Files.File;
- R: Files.Rider;
- c, nextc: Constellation;
- p, nextp: Star;
- buf: Graph;
- BEGIN
- cpBuf := Files.New("");
- Files.Set(R, cpBuf, 0);
- Reset; from.WriteSel(R);
- Files.Set(R, cpBuf, 0); Types.NewObj(buf, Types.TypeOf(from)); buf.notify := Dummy;
- Reset; buf.Read(R);
- p := buf.stars;
- WHILE p # NIL DO nextp := p.next;
- INC(p.x, dx); INC(p.y, dy);
- IF (p.refcnt > 0) OR (p IS Planet) THEN G.Append(p) END;
- p := nextp
- END ;
- c := buf.cons; KeplerPorts.InitBalloon(update);
- WHILE c # NIL DO c.Draw(update); nextc := c.next;
- IF G.cons = NIL THEN G.cons := c ELSE G.lastcons.next := c END ;
- G.lastcons := c; c.next := NIL;
- c := nextc
- END ;
- G.notify(restore, G, NIL, update)
- END CopySelection;
- PROCEDURE (G: Graph) SendToBack* (o: Object);
- VAR i: INTEGER;
- s: Star;
- c: Constellation;
- BEGIN
- WITH
- o: Star DO
- s := G.stars;
- IF o # s THEN
- WHILE s.next # o DO s := s.next END ;
- s.next := o.next; o.next := G.stars; G.stars := o;
- IF G.laststar = o THEN G.laststar := s END ;
- IF o IS Planet THEN (* preserve topological order *)
- c := o(Planet).c;
- FOR i := 0 TO c.nofpts-1 DO
- G.SendToBack(c.p[i])
- END
- END
- END
- | o: Constellation DO
- KeplerPorts.InitBalloon(update);
- c := G.cons;
- IF o # c THEN
- WHILE c.next # o DO c := c.next END ;
- c.next := o.next; o.next := G.cons; G.cons := o;
- IF G.lastcons = o THEN G.lastcons := c END ;
- o.Draw(update);
- G.notify(restore, G, NIL, update)
- END
- END
- END SendToBack;
- PROCEDURE Unrelease(c: Constellation);
- VAR i: INTEGER;
- BEGIN i := 0;
- WHILE i < c.nofpts DO INC(c.p[i].refcnt); INC(i) END
- END Unrelease;
- PROCEDURE Recall*;
- VAR s, nexts: Star; c, nextc: Constellation;
- BEGIN
- IF delG # NIL THEN
- s := del.stars;
- WHILE s # NIL DO
- nexts := s.next; s.sel := FALSE; delG.Append(s);
- IF s IS Planet THEN Unrelease(s(Planet).c) END ;
- s := nexts
- END ;
- c := del.cons;
- WHILE c # NIL DO nextc := c.next; delG.Append(c); Unrelease(c); c := nextc END ;
- delG := NIL; del.cons := NIL; del.lastcons := NIL; del.stars := NIL; del.laststar := NIL
- END
- END Recall;
- BEGIN NEW(update); NEW(del); NEW(starTab, 1)
- END KeplerGraphs.
-